package com.knowledge.business.service.impl;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.knowledge.business.domain.KnowledgeDocumentSegment;
import com.knowledge.business.service.IKnowledgeDocumentSegmentService;
import com.knowledge.common.AliyunOssUploadUtils;
import com.knowledge.common.core.domain.AjaxResult;
import com.knowledge.common.utils.*;
import com.knowledge.common.utils.http.HttpUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.knowledge.business.mapper.KnowledgeDocumentMapper;
import com.knowledge.business.domain.KnowledgeDocument;
import com.knowledge.business.service.IKnowledgeDocumentService;

/**
 * 知识库文档Service业务层处理
 *
 * @author zhaoyk
 * @date 2025-09-13
 */
@Service
public class KnowledgeDocumentServiceImpl extends ServiceImpl<KnowledgeDocumentMapper, KnowledgeDocument> implements IKnowledgeDocumentService {
    @Autowired
    private KnowledgeDocumentMapper knowledgeDocumentMapper;
    @Autowired
    private IKnowledgeDocumentSegmentService knowledgeDocumentSegmentService;

    private static final Logger log = LoggerFactory.getLogger(KnowledgeDocumentServiceImpl.class);

    // 正则表达式：匹配 Markdown 图片格式 ![描述文本](图片URL)
    private static final Pattern MARKDOWN_IMAGE_PATTERN = Pattern.compile("!\\[(.*?)\\]\\((.*?)\\)");
    // 开关：true=提取为纯URL，false=保留Markdown格式（替换为自有OSS链接）
    private static final boolean EXTRACT_PURE_URL = true;


    @Autowired
    private HtmlFileUtil htmlFileUtil;


    /**
     * 查询知识库文档
     *
     * @param id 知识库文档主键
     * @return 知识库文档
     */
    @Override
    public KnowledgeDocument selectKnowledgeDocumentById(String id) {
        return knowledgeDocumentMapper.selectKnowledgeDocumentById(id);
    }

    /**
     * 查询知识库文档列表
     *
     * @param knowledgeDocument 知识库文档
     * @return 知识库文档
     */
    @Override
    public List<KnowledgeDocument> selectKnowledgeDocumentList(KnowledgeDocument knowledgeDocument) {
        return knowledgeDocumentMapper.selectKnowledgeDocumentList(knowledgeDocument);
    }

    /**
     * 新增知识库文档
     *
     * @return 结果
     */
    @Override
    public KnowledgeDocument insertKnowledgeDocument(KnowledgeDocument vo) throws Exception {

        // 在主线程中设置基础字段
        vo.setUserId(SecurityUtils.getUserIdStr());
        vo.setCreateBy(SecurityUtils.getUserIdStr());
        vo.setCreateTime(DateUtils.getNowDate());
        if ("1".equals(vo.getDocumentType()) || "2".equals(vo.getDocumentType()) || "4".equals(vo.getDocumentType())) {
            String fileUrl = vo.getFileUrl();
            String name = FileUtil.getName(fileUrl);
            vo.setDocumentTitle(StringUtils.isEmpty(vo.getDocumentTitle()) ? name : vo.getDocumentTitle());
            String fileType = FileUtil.getSuffix(fileUrl);
            vo.setFileType(fileType);
        } else {
            vo.setDocumentTitle(StringUtils.isEmpty(vo.getUrl()) ? "无标题" : vo.getUrl());
        }
        vo.setIsFolder("0");
        // 先保存基础信息
        knowledgeDocumentMapper.insertKnowledgeDocument(vo);

        // 异步执行文档解析
        CompletableFuture.runAsync(() -> {
            try {
                log.warn("开始文档解析======================================");
                doJxDocument(vo);
                log.warn("结束文档解析======================================");
            } catch (Exception e) {
                log.error("异步解析文档失败", e);
            }
        });
        return vo;
    }


    public void doJxDocument(KnowledgeDocument vo) throws Exception {
        String documentType = vo.getDocumentType();
        // 设置初始解析状态
        vo.setParseStatus("Init");
        try {
            String parseId = "";
            Boolean needParse = false;
            // 根据文档类型获取解析ID
            if ("3".equals(documentType)) {
                if(StringUtils.isEmpty(vo.getUrl())){
                    throw new Exception("请填写网站链接");
                }
                // 先过滤一遍再提交解析任务
                Path path = htmlFileUtil.fetchAndSaveToTempFile(vo.getUrl());
                System.out.println("临时文件路径：" + path.toAbsolutePath());
                // 将 Path 转换为 File 对象
                File file = path.toFile();
                parseId = AliYunFileParserUtils.submitDocParserJob(file, FileUtil.getName(file));
                needParse = true;
                vo.setParseStatus("Processing");
            } else if ("2".equals(documentType) || "4".equals(documentType)) {
                // 图片和视频
                vo.setParseStatus("Success");
                vo.setDocumentContent(vo.getDocumentContent() + "" + vo.getFileUrl());
            } else {
                String fileUrl = vo.getFileUrl();
                parseId = AliYunFileParserUtils.submitDocParserJobByUrl(fileUrl, vo.getDocumentTitle());
                vo.setParseStatus("Processing");
                needParse = true;
            }
            vo.setParseId(parseId);
            this.updateById(vo);
            if (needParse) {
                // 等待解析完成并获取阿里云Markdown格式文档
                String documentContent = AliYunFileParserUtils.parseFileWithAliyun(parseId, vo.getDocumentType());
                // 替换图片中路径
                String newDocumentContent = OssChangeUtil.getNewDocumentContent(documentContent, vo.getTypeId(), vo.getId());
                // 更新文档状态和内容
                if (StringUtils.isEmpty(documentContent)) {
                    vo.setParseStatus("F");
                    vo.setParseMsg("解析后文档内容为空");
                } else {
                    vo.setDocumentContent(newDocumentContent);
                    vo.setParseStatus("Success");
                    vo.setRemark("原始解析内容：" + documentContent.substring(0, Math.min(documentContent.length(), 500)) + "..."); // 备注截取前500字符
                }
                this.updateById(vo);
                log.info("文档解析处理完成：docId={}, 状态={}");
            }

        } catch (Exception e) {
            vo.setParseStatus("Fail");
            vo.setParseMsg("提交文档解析任务失败：" + e.getMessage());
            this.updateById(vo);
            log.error("文档解析任务异常：docId={}, 异常信息={}");
            throw e; // 抛出异常供上层处理（如告警）
        }
    }

    /**
     * 修改知识库文档
     *
     * @return 结果
     */
    @Override
    public int updateKnowledgeDocument(KnowledgeDocument vo) throws Exception {
        this.doJxDocument(vo);
        vo.setUpdateTime(DateUtils.getNowDate());
        return 1;
    }

    /**
     * 批量删除知识库文档
     *
     * @param ids 需要删除的知识库文档主键
     * @return 结果
     */
    @Override
    public int deleteKnowledgeDocumentByIds(String[] ids) {
        return knowledgeDocumentMapper.deleteKnowledgeDocumentByIds(ids);
    }

    /**
     * 删除知识库文档信息
     *
     * @param id 知识库文档主键
     * @return 结果
     */
    @Override
    public int deleteKnowledgeDocumentById(String id) {
        return knowledgeDocumentMapper.deleteKnowledgeDocumentById(id);
    }

    @Autowired
    VectorStorageService storageService;

    @Autowired
    AliyunOssUploadUtils aliyunOssUploadUtils;


    @Override
    public void deleteSj(String[] ids) {
        QueryWrapper<KnowledgeDocumentSegment> knowledgeDocumentSegmentQueryWrapper = new QueryWrapper<>();
        knowledgeDocumentSegmentQueryWrapper.in("document_id", Arrays.asList(ids));
        knowledgeDocumentSegmentService.remove(knowledgeDocumentSegmentQueryWrapper);
        // 删除向量数据库中的内容
        storageService.deleteDocumentVectorsByDocumentIds(Arrays.asList(ids));
        for (int i = 0; i < ids.length; i++) {
            // 删除oss 中的文件
            String documentId = ids[i];
            KnowledgeDocument byId = this.getById(documentId);
            String id = byId.getId();
            // 删除阿里云文件
            aliyunOssUploadUtils.deleteFileByForder(byId.getTypeId() + "/" + id);
        }
        this.removeByIds(Arrays.asList(ids));
    }
}
